/*
 * @Description: 分组柱状图
 * @Author: YoungWind
 * @Date: 2020-09-27 15:06:40
 * @LastEditTime: 2020-09-27 18:10:11
 * @LastEditors: YoungWind
 * @FilePath: \ccd3\src\ccd3\bar\charts\GroupedBar.js
 */
import BaseChart from '../../BaseChart.js'

export default class GroupedBar extends BaseChart {
  constructor(id, data) {
    super(id, data)

    this.groupKey = 'x';
    this.filterKeys = [];
    this.yAxisTitle = 'title';

    this.xAxis = null;
    //根据groupKey先进行第一层分组
    this.xAxisScale = null;
    this.xAxisGroup = null;
    //根据keys再进行第二层分组
    this.xKeysAxisScale = null;

    this.yAxis = null;
    this.xAxisScale = null;
    this.yAxisGroup = null;

    this.rectsGroup = null;
    this.legend = null;
    this.legendGroup = null;
    this.color = d3.schemeCategory10;
  }

  /**
   * @description: 设置X轴字段
   * @param {type} 
   * @return {type} 
   */
  setGroupKey(name) {
    this.groupKey = name;
    return this;
  }
  /**
   * @description: 设置需要过滤的字段
   * @param {type} 
   * @return {type} 
   */
  setFilterKeys(arr) {
    this.filterKeys = arr;
    return this;
  }
  /**
   * @description: 设置y轴标题
   * @param {type} 
   * @return {type} 
   */
  setYAxisTitle(title) {
    this.yAxisTitle = title;
    return this;
  }

  /**
   * @description: 初始化
   * @param {type} 
   * @return {type} 
   */
  init() {
    this.initSvg();
    this.initMainGroup();
    this.initAxes();
    this.initRects();
    this.initLegend();
    return this;
  }

  /**
   * @description: 初始化坐标轴
   * @param {type} 
   * @return {type} 
   */
  initAxes() {
    this.xAxisGroup = this.svg.append('g')
      .attr('id', `${this.id}xAxis`)
      .attr('transform', `translate(${this.margin.left},${this.margin.top + this.innerHeight})`);

    this.yAxisGroup = this.svg.append('g')
      .attr('id', `${this.id}yAxis`)
      .attr('transform', `translate(${this.margin.left},${this.margin.top})`);
  }

  /**
   * @description: 初始化柱状图
   * @param {type} 
   * @return {type} 
   */
  initRects() {
    this.rectsGroup = this.mg.append('g')
      .attr('id', `${this.id}rectsGroup`)
  }

  /**
   * @description: 初始化标题尺
   * @param {type} 
   * @return {type} 
   */
  initLegend() {
    this.legendGroup = this.mg.append('g')
      .attr('id', `${this.id}LegendGroup`)
      .attr("transform", `translate(${this.innerWidth},0)`)
  }

  /**
   * @description: 渲染视图
   * @param {type} 
   * @return {type} 
   */
  render(data) {
    if (data) {
      this.data = data;
    }
    this.renderData();
    this.renderScale();
    this.renderAxes();
    this.renderRects();
    this.renderLegend();
    return this;
  }

  /**
   * @description: 处理更新后的数据
   * @param {type} 
   * @return {type} 
   */
  renderData() {
    //过滤数据
    this.keys = this.data.columns.filter(d => !this.filterKeys.includes(d) && d !== this.groupKey);
  }

  /**
   * @description: 更新坐标轴比例尺
   * @param {type} 
   * @return {type} 
   */
  renderScale() {
    this.xAxisScale = d3.scaleBand()
      .domain(this.data.map(d => d[this.groupKey]))
      .rangeRound([0, this.innerWidth])
      .paddingInner(0.1)

    this.xKeysAxisScale = d3.scaleBand()
      .domain(this.keys)
      .rangeRound([0, this.xAxisScale.bandwidth()])
      .padding(0.05)

    this.yAxisScale = d3.scaleLinear()
      .domain([0, d3.max(this.data, d => d3.max(this.keys, key => +d[key]))])
      .nice()
      .rangeRound([this.innerHeight, 0])

    this.colorScale = d3.scaleOrdinal()
      .domain(this.keys)
      .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
  }

  /**
   * @description: 更新坐标轴 
   * @param {type} 
   * @return {type} 
   */
  renderAxes() {
    this.xAxis = this.xAxisGroup.transition()
      .call(d3.axisBottom(this.xAxisScale))

    this.yAxis = this.yAxisGroup

    this.yAxis.transition().call(d3.axisLeft(this.yAxisScale).ticks(null, 's'));

    this.yAxis.call(g => g.select(".tick:last-of-type text")
      .clone()
      .attr("x", 3)
      .attr("text-anchor", "start")
      .attr("font-weight", "bold")
      .text(this.yAxisTitle));
  }

  /**
   * @description: 绘制柱状图
   * @param {type} 
   * @return {type} 
   */
  renderRects() {
    this.rectsGroups = this.rectsGroup
      .selectAll("g")
      .data(this.data)
      .join("g")

    this.rectsGroups.transition()
      .attr("transform", d => `translate(${this.xAxisScale(d[this.groupKey])},0)`);

    this.rects = this.rectsGroups
      .selectAll("rect")
      .data(d => this.keys.map(key => ({ key, value: d[key] })))
      .join("rect");

    this.rects.transition()
      .attr("x", d => this.xKeysAxisScale(d.key))
      .attr("y", d => this.yAxisScale(d.value))
      .attr("width", this.xKeysAxisScale.bandwidth())
      .attr("height", d => this.yAxisScale(0) - this.yAxisScale(d.value))
      .attr("fill", d => this.colorScale(d.key));
  }

  /**
   * @description: 更新标题
   * @param {type} 
   * @return {type} 
   */
  renderLegend() {
    this.legend = this.legendGroup
      .attr("text-anchor", "end")
      .attr("font-family", "sans-serif")
      .attr("font-size", 10)
      .selectAll("g")
      .data(this.colorScale.domain().slice().reverse())
      .join("g")
      .attr("transform", (d, i) => `translate(0,${i * 20})`);

    this.legend.append("rect")
      .attr("x", -19)
      .attr("width", 19)
      .attr("height", 19)
      .attr("fill", this.colorScale);

    this.legend.append("text")
      .attr("x", -24)
      .attr("y", 9.5)
      .attr("dy", "0.35em")
      .text(d => d);
  }
}